#include "DS18B20.h"

WifiIotGpioValue DS18B20_DQ_IN;

void DS18B20_SetIn(void)
{
    GpioSetDir(WIFI_IOT_IO_NAME_GPIO_10, WIFI_IOT_GPIO_DIR_IN);
    IoSetPull(WIFI_IOT_IO_NAME_GPIO_10, WIFI_IOT_IO_PULL_NONE);
}

void DS18B20_SetOut(void)
{
    GpioSetDir(WIFI_IOT_IO_NAME_GPIO_10, WIFI_IOT_GPIO_DIR_OUT);
}

WifiIotGpioValue GPIOGetInputValue(WifiIotIoName id, WifiIotGpioValue *value)
{
   GpioGetInputVal(id, value);
   return *value;
}

void DS18B20_Reset(void)
{
    DS18B20_SetOut();
    GpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_10, WIFI_IOT_GPIO_VALUE0);
    usleep(750);
    GpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_10, WIFI_IOT_GPIO_VALUE1);
    hi_udelay(15);
}

bool DS18B20_Check(void)
{
    uint8_t t = 0;
    DS18B20_SetIn();
    while(GPIOGetInputValue(WIFI_IOT_IO_NAME_GPIO_10, &DS18B20_DQ_IN) && t < 200)
    {
        t ++;
        hi_udelay(1);
    }
    if(t >= 200)
    {
        printf("\nError: Waiting Response Overtime!Non-Respond!");
        return false;
    }
    else
    {
        t = 0;
    }
    while((!GPIOGetInputValue(WIFI_IOT_IO_NAME_GPIO_10, &DS18B20_DQ_IN)) && t < 240)
    {
        t ++;
        hi_udelay(1);
    }
    if(t >= 240)
    {
        printf("\nError: Responsing Overtime! \n");
        return false;
    }
    printf("\nResponse is OK !(t = %d)",t);
    return true;
}

bool DS18B20_Init(void)
{
    GpioInit();
    DS18B20_SetOut();
    GpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_10, WIFI_IOT_GPIO_VALUE1);
    DS18B20_Reset();
    return DS18B20_Check();
}

void DS18B20_WriteByte(uint8_t byte)
{
    uint8_t i,test = 0;
    DS18B20_SetOut();
    for(i = 1; i <= 8; i ++)
    {
        test = byte & 0x01;
        byte = byte >> 1;
        if(test)
        {
            GpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_10, 0);
            hi_udelay(2);
            GpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_10, 1);
            hi_udelay(60);
        }
        else
        {
            GpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_10, 0);
            hi_udelay(60);
            GpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_10, 1);
            hi_udelay(2);
        }
    }
}

WifiIotGpioValue DS18B20_ReadBit(void)
{
    DS18B20_SetOut();
    GpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_10, 0);
    hi_udelay(2);
    GpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_10, 1);

    DS18B20_SetIn();
    hi_udelay(12);
    
    if(GPIOGetInputValue(WIFI_IOT_IO_NAME_GPIO_10, &DS18B20_DQ_IN))
    {  
        hi_udelay(50);
        return WIFI_IOT_GPIO_VALUE1;
    }
    else
    {
        hi_udelay(50);
        return WIFI_IOT_GPIO_VALUE0;
    }
}

uint8_t DS18B20_ReadByte(void)
{
    uint8_t i,j,data = 0;
    for(i = 1; i <= 8; i ++)
    {
        j = DS18B20_ReadBit();
        data = (j<<7) | (data>>1);
        hi_udelay(2);
    }
    return data;
}

bool DS18B20_GetData(float *temp)
{
    uint8_t dataL,dataH;
    uint16_t tempeData;
    bool positive;
    float result;

    DS18B20_Reset();
    if(DS18B20_Check())
    {
        DS18B20_WriteByte(0xCC);
        DS18B20_WriteByte(0x44);

        DS18B20_Reset();
        if(DS18B20_Check())
        {
            DS18B20_WriteByte(0xCC);
            DS18B20_WriteByte(0xBE);
            dataL = DS18B20_ReadByte();
            dataH = DS18B20_ReadByte();

            if(dataH > 7)
            {
                dataH = ~dataH;
                dataL = ~dataL;
                positive = false;
            }
            else
            {
                positive = true;
            }

            tempeData = dataH;
            tempeData = tempeData << 8;
            tempeData += dataL;
            result = (float)tempeData * 0.0625;

            if(positive)
            {
                *temp = result;
            }
            else
            {
                *temp = -result;
            }
            return true;
        }
        else
        {
            return false;
        }
    }
    else
    {
        return false;
    }
}
